package meta

import UtilFuncs
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import java.io.FileWriter
import java.io.PrintWriter
import java.lang.Exception

sealed class Entity (var id:String, var name:String, var code:String)

interface TreeModel<T> {
    var parentId:String
    var children:MutableList<T>
    var route:String
    fun path():String
}

interface DeepCopy<out R>{
    fun deepCopy(): R
}


class Station (id:String, name:String, code:String,
               override var parentId: String, override var children: MutableList<Entity>, override var route: String,
               voltageLevel:String = "", industryCategory:String = "", industryType:String = "", population:Int = 0,
               area:Float = 100.0F, legalPerson:String = "", contact:String = "", dutyParagraph:String = "",
               memo:String = "") : Entity(id, name, code), TreeModel<Entity> {
    override fun path () = route
}

class InlineSwitch (id:String, name: String, code: String,
                    override var parentId: String, override var children:MutableList<Entity>, override var route: String,
                    inVol:String = "", outVol:String = "", type: String = "", memo: String = ""): Entity(id, name, code),
    TreeModel<Entity> {
    override fun path () = "$route->$id"
}

class Transformer (id:String, name: String, code: String,
                   override var parentId: String, override var children:MutableList<Entity>, override var route: String,
                   currentRatio:String = "", voltageRatio:String = "", memo: String = ""): Entity(id, name, code),
    TreeModel<Entity> {
    override fun path () = "$route->$id"
}

class OutlineSwitch (id:String, name: String, code: String,
                     override var parentId: String, override var children:MutableList<Entity>, override var route: String,
                    ): Entity(id, name, code), TreeModel<Entity> {
    override fun path () = "$route->$id"
}

class ChargingPile (id:String, name: String, code: String,
                    override var parentId: String, override var children:MutableList<Entity>, override var route: String,
                    capacity:Float): Entity(id, name, code), TreeModel<Entity> {
    override fun path () = "$route->$id"
}


class ContactSwitch (id:String, name: String, code: String,
                     override var parentId: String, override var children:MutableList<Entity>, override var route: String,
                     state: String = "normal"): Entity(id, name, code), TreeModel<Entity> {
    override fun path () = "$route->$id"
}

class Diesel (id:String, name: String, code: String,
              override var parentId: String, override var children:MutableList<Entity>, override var route: String,
              capacity:Float): Entity(id, name, code), TreeModel<Entity> {
    override fun path () = "$route->$id"
}

class Photovoltaic (id:String, name: String, code: String,
                    override var parentId: String, override var children:MutableList<Entity>, override var route: String,
                    capacity:Float): Entity(id, name, code), TreeModel<Entity> {
    override fun path () = "$route->$id"
}

class BatteryStation(id:String, name: String, code: String,
                     override var parentId: String, override var children:MutableList<Entity>, override var route: String,
                     maxPower:Float, capacity: Float): Entity(id, name, code), TreeModel<Entity> {
    override fun path () = "$route->$id"
}

class BuildingLoad(id:String, name: String, code: String,
                   override var parentId: String, override var children:MutableList<Entity>, override var route: String
                    ): Entity(id, name, code), TreeModel<Entity> {
    override fun path () = "$route->$id"
}

class FloorLoad(id:String, name: String, code: String,
                override var parentId: String, override var children:MutableList<Entity>, override var route: String
                ): Entity(id, name, code), TreeModel<Entity> {
    override fun path () = "$route->$id"
}

class RoomLoad(id:String, name: String, code: String,
               override var parentId: String, override var children:MutableList<Entity>, override var route: String
               ): Entity(id, name, code), TreeModel<Entity> {
    override fun path () = "$route->$id"
}

class Appliance(id:String, name: String, code: String,
                override var parentId: String, override var children:MutableList<Entity>, override var route: String
                ): Entity(id, name, code), TreeModel<Entity> {
    override fun path () = "$route->$id"
}


class PhysicalMaster {

    lateinit var root: Entity

    init {
        UtilFuncs.counterFormat(length = 5, refresh = true)

        createRoot() //创建学校根目录
        appendInline() // 高压进线
        appendTransformer() // 变压器
        appendOutlines() //低压出线开关

        appendChargingPile() //充电桩
        appendContactSwitch()  //2个低压联络开关

        appendDiesel() // 柴油发电机和微网分路开关

        appendMicroGrid1() // 微网1（创新楼）
        appendMicroGrid2() // 微网2 （信息中心）

        appendBuildingGroup1() // 微网1楼宇群分路开关
        appendBuildingGroup2() // 微网2楼宇群分路开关

        createBuildingHoude()// 厚德阁
        createBuildingWendao()// 问道阁
        createBuildingGreen()// 绿色楼
        createBuildingInnovation()// 创新楼
        createBuildingOpen()// 开放楼
        createBuildingZhiwei()// 知味园餐厅
        createBuildingCanting()// 知味园厨房

    }

    fun saveMetaFile(savePath: String){
        try {
            PrintWriter(FileWriter(savePath)).use {
                val gson = GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create()
                val rootStr = gson.toJson(root)
                it.write(rootStr)
            }
        }catch (e: Exception){
            e.printStackTrace()
        }
    }

    fun depthTraversal() = depthRecursion(root as TreeModel<Entity>)

    private fun depthRecursion(node: TreeModel<Entity>){
        val localNode = node as Entity
        println("${localNode.id} + ${localNode.name} + ${localNode.code} + ${node.path()}")
        val treeNode = node as TreeModel<*>
        if (treeNode.children.size == 0){
            println("叶子节点")
        }else{
            treeNode.children.forEach { depthRecursion(it as TreeModel<Entity>) }
        }
    }

    fun widthTraversal() {
        val recursionList = mutableListOf(root as TreeModel<Entity>)
        while (recursionList.size > 0){
            val curNode = recursionList[0]
            val localNode = curNode as Entity
            println("${localNode.id} + ${localNode.name} + ${localNode.code} + ${curNode.path()}")
            recursionList.removeAt(0)
            curNode.children.forEach { recursionList.add(it as TreeModel<Entity>) }
        }
    }

    fun createRoot(){
        root = Station("HAINAN-UNIVERISTY-${UtilFuncs.counterFormat(5, "0")}", "海南电校", "Enterprise-${UtilFuncs.unique(16)[0]}", "root", mutableListOf(),
            "root", "10kV","第三产业","居民生活用电", 10000, 95131.0F, "徐慧琳", "0898-65317710", "91460100MA5T2MGD14")
    }

    fun findTreeNode(codeStr: String): Entity?{
        val recursionList = mutableListOf(root as Entity)
        while (recursionList.size > 0){
            val curNode = recursionList[0]
            if (curNode.code.contains(codeStr, ignoreCase = true))
                return curNode
            recursionList.removeAt(0)
            val localNode = curNode as TreeModel<Entity>
            localNode.children.forEach { recursionList.add(it) }
        }
        return null
    }

    fun appendInline(){
        val rootTreeNode = root as TreeModel<Entity>
        val inSwitch = InlineSwitch("INLINE-SWITCH-${UtilFuncs.counterFormat(5, "1")}", "进线开关(计量点)", "InSwitch-${UtilFuncs.unique(16)[0]}", root!!.id,
            mutableListOf(), rootTreeNode.path(), "10kV", "0.4kV", "3元件计量")
        rootTreeNode.children.add(inSwitch)
    }

    fun appendTransformer(){
        val rootTreeNode = root as TreeModel<Entity>
        val transformer = Transformer("TRANSFORMER-SCB-${UtilFuncs.counterFormat(5, "1")}", "800kVA厢式变压器", "Transformer-${UtilFuncs.unique(16)[0]}", root!!.id,
            mutableListOf(), rootTreeNode!!.path(),"100/4", "15/5")
        rootTreeNode.children.add(transformer)
    }

    fun appendOutlines(){
        val rootTreeNode = root as TreeModel<Entity>
        val out_backup1 = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "1")}", "备用1", "Backup1-${UtilFuncs.unique(16)[0]}", root!!.id, mutableListOf(), rootTreeNode.path())
        val out_backup2 = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "1")}", "备用2", "Backup2-${UtilFuncs.unique(16)[0]}", root!!.id, mutableListOf(), rootTreeNode.path())
        val water_pump = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "1")}", "水泵房(可中断)", "WaterPump-${UtilFuncs.unique(16)[0]}", root!!.id, mutableListOf(), rootTreeNode.path())
        val sewage_station = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "1")}", "污水站", "Sewage-${UtilFuncs.unique(16)[0]}", root!!.id, mutableListOf(), rootTreeNode.path())
        val out_backup3 = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "1")}", "备用3", "Backup3-${UtilFuncs.unique(16)[0]}", root!!.id, mutableListOf(), rootTreeNode.path())
        val zhiwei_park = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "1")}", "知味园(厨房)", "ZhiweiImportant-${UtilFuncs.unique(16)[0]}", root!!.id, mutableListOf(), rootTreeNode.path())
        val innovation_park = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "1")}", "创新楼(总出线)", "Innovation-${UtilFuncs.unique(16)[0]}", root!!.id, mutableListOf(), rootTreeNode.path())
        val street_lamp = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "1")}", "路灯", "Lamp-${UtilFuncs.unique(16)[0]}", root!!.id, mutableListOf(), rootTreeNode.path())
        val shunt_switch = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "1")}", "联络开关", "CSwitch-${UtilFuncs.unique(16)[0]}", root!!.id, mutableListOf(), rootTreeNode.path())
        rootTreeNode.children.add(out_backup1)
        rootTreeNode.children.add(out_backup2)
        rootTreeNode.children.add(water_pump)
        rootTreeNode.children.add(sewage_station)
        rootTreeNode.children.add(out_backup3)
        rootTreeNode.children.add(zhiwei_park)
        rootTreeNode.children.add(innovation_park)
        rootTreeNode.children.add(street_lamp)
        rootTreeNode.children.add(shunt_switch)
    }

    fun appendChargingPile(){
        val backup3Code = findTreeNode("Backup3")
        val backupTreeNode = backup3Code as TreeModel<Entity>
        val pile1 = ChargingPile("CHARGINGPILE-FAST-${UtilFuncs.counterFormat(5, "2")}", "60kW快充桩1", "Charging-${UtilFuncs.unique(16)[0]}", backup3Code.id, mutableListOf(), backup3Code.path(),60F)
        val pile2 = ChargingPile("CHARGINGPILE-FAST-${UtilFuncs.counterFormat(5, "2")}", "60kW快充桩1", "Charging-${UtilFuncs.unique(16)[0]}", backup3Code.id, mutableListOf(), backup3Code.path(),60F)
        val pile3 = ChargingPile("CHARGINGPILE-SLOW-${UtilFuncs.counterFormat(5, "2")}", "7kW快充桩1", "Charging-${UtilFuncs.unique(16)[0]}", backup3Code.id, mutableListOf(), backup3Code.path(), 7F)
        val pile4 = ChargingPile("CHARGINGPILE-SLOW-${UtilFuncs.counterFormat(5, "2")}", "7kW快充桩1", "Charging-${UtilFuncs.unique(16)[0]}", backup3Code.id, mutableListOf(), backup3Code.path(),7F)
        val pile5 = ChargingPile("CHARGINGPILE-SLOW-${UtilFuncs.counterFormat(5, "2")}", "7kW快充桩1", "Charging-${UtilFuncs.unique(16)[0]}", backup3Code.id, mutableListOf(), backup3Code.path(),7F)
        val pile6 = ChargingPile("CHARGINGPILE-SLOW-${UtilFuncs.counterFormat(5, "2")}", "7kW快充桩1", "Charging-${UtilFuncs.unique(16)[0]}", backup3Code.id, mutableListOf(), backup3Code.path(),7F)
        backupTreeNode.children.add(pile1)
        backupTreeNode.children.add(pile2)
        backupTreeNode.children.add(pile3)
        backupTreeNode.children.add(pile4)
        backupTreeNode.children.add(pile5)
        backupTreeNode.children.add(pile6)
    }

    fun appendContactSwitch(){
        val innovationNode = findTreeNode("Innovation")
        val backup3Node = findTreeNode("CSwitch")
        val innovationTreeNode = innovationNode as TreeModel<Entity>
        val backup3TreeNode = backup3Node as TreeModel<Entity>
        val ats1 = ContactSwitch("INNOVATION-CONTACTOR-${UtilFuncs.counterFormat(5, "2")}", "创新楼联络开关", "ContactSwitch1-${UtilFuncs.unique(16)[0]}", innovationNode.id, mutableListOf(), innovationTreeNode.path(), "normal")
        val ats2 = ContactSwitch("INNOVATION-CONTACTOR-${UtilFuncs.counterFormat(5, "2")}", "区域2联络开关", "ContactSwitch2-${UtilFuncs.unique(16)[0]}", backup3Node.id, mutableListOf(), backup3Node.path(),"normal")
        innovationTreeNode.children.add(ats1)
        backup3TreeNode.children.add(ats2)
    }

    fun appendDiesel(){
        val switch1 = findTreeNode("ContactSwitch1")
        val switch1TreeNode = switch1 as TreeModel<Entity>
        val diesel1 = Diesel("DIESEL-EMERGENCY-${UtilFuncs.counterFormat(5, "3")}", "柴油发电机1", "Diesel-${UtilFuncs.unique(16)[0]}", switch1.id, mutableListOf(), switch1.path(),220F)
        val microGridSwitch1 = OutlineSwitch("MICROGRID-SWITCH-${UtilFuncs.counterFormat(5, "3")}", "微网1离并网切换开关", "Microgrid1-${UtilFuncs.unique(16)[0]}", switch1.id, mutableListOf(), switch1.path())
        switch1TreeNode.children.add(diesel1)
        switch1TreeNode.children.add(microGridSwitch1)

        val switch2 = findTreeNode("ContactSwitch2")
        val switch2TreeNode = switch2 as TreeModel<Entity>
        val diesel2 = Diesel("DIESEL-EMERGENCY-${UtilFuncs.counterFormat(5, "3")}", "柴油发电机2", "Diesel-${UtilFuncs.unique(16)[0]}", switch2.id, mutableListOf(),switch2.path(), 350F)
        val microGridSwitch2 = OutlineSwitch("MICROGRID-SWITCH-${UtilFuncs.counterFormat(5, "3")}", "微网2离并网切换开关", "Microgrid2-${UtilFuncs.unique(16)[0]}", switch2.id, mutableListOf(), switch2.path())
        switch2TreeNode.children.add(diesel2)
        switch2TreeNode.children.add(microGridSwitch2)
    }

    fun appendMicroGrid1(){
        val microGrid = findTreeNode("Microgrid1")
        val microGridTreeNode = microGrid as TreeModel<Entity>
        val pv1 = Photovoltaic("PV-LOW-${UtilFuncs.counterFormat(5, "4")}", "创新楼光伏", "InnovationPV-${UtilFuncs.unique(16)[0]}", microGrid.id, mutableListOf(), microGridTreeNode.path(), 26.24F)
        val pv2 = Photovoltaic("PV-LOW-${UtilFuncs.counterFormat(5, "4")}", "厚德阁光伏", "HoudePV-${UtilFuncs.unique(16)[0]}", microGrid.id, mutableListOf(), microGridTreeNode.path(), 22.14F)
        val battery = BatteryStation("BATTERY-LOW-${UtilFuncs.counterFormat(5, "4")}", "电池储能1", "Battery1-${UtilFuncs.unique(16)[0]}", microGrid.id, mutableListOf(), microGridTreeNode.path(), 100F, 100F)
        val switch = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "4")}", "微网1分路开关", "BuildingGroup1-${UtilFuncs.unique(16)[0]}", microGrid.id, mutableListOf(), microGridTreeNode.path())
        microGridTreeNode.children.add(pv1)
        microGridTreeNode.children.add(pv2)
        microGridTreeNode.children.add(battery)
        microGridTreeNode.children.add(switch)
    }

    fun appendMicroGrid2(){
        val microGrid = findTreeNode("Microgrid2")
        val microGridTreeNode = microGrid as TreeModel<Entity>
        val pv1 = Photovoltaic("PV-LOW-${UtilFuncs.counterFormat(5, "4")}", "绿色楼光伏", "GreenPV-${UtilFuncs.unique(16)[0]}", microGrid.id, mutableListOf(), microGrid.path(),26.24F)
        val pv2 = Photovoltaic("PV-LOW-${UtilFuncs.counterFormat(5, "4")}", "知味园光伏", "ZhiweiPV-${UtilFuncs.unique(16)[0]}", microGrid.id, mutableListOf(), microGrid.path(),45.92F)
        val battery = BatteryStation("BATTERY-LOW-${UtilFuncs.counterFormat(5, "4")}", "电池储能2", "Battery2-${UtilFuncs.unique(16)[0]}", microGrid.id, mutableListOf(), microGrid.path(),200F, 200F)
        val switch = OutlineSwitch("OUTLINE-SWITCH-${UtilFuncs.counterFormat(5, "4")}", "微网2分路开关", "BuildingGroup2-${UtilFuncs.unique(16)[0]}", microGrid.id, mutableListOf(), microGrid.path())
        microGridTreeNode.children.add(pv1)
        microGridTreeNode.children.add(pv2)
        microGridTreeNode.children.add(battery)
        microGridTreeNode.children.add(switch)
    }

    fun appendBuildingGroup1(){
        val buidlingGroup = findTreeNode("Microgrid1")
        val buidlingTreeNode = buidlingGroup as TreeModel<Entity>
        val building1 = BuildingLoad("BUILDING-LOW-${UtilFuncs.counterFormat(5, "5")}", "创新楼", "BuildingInnovation-${UtilFuncs.unique(16)[0]}", buidlingGroup.id, mutableListOf(), buidlingTreeNode.path())
        val building2 = BuildingLoad("BUILDING-LOW-${UtilFuncs.counterFormat(5, "5")}", "厚德阁", "BuildingHoude-${UtilFuncs.unique(16)[0]}", buidlingGroup.id, mutableListOf(), buidlingTreeNode.path())
        buidlingTreeNode.children.add(building1)
        buidlingTreeNode.children.add(building2)
    }

    fun appendBuildingGroup2(){
        val buidlingGroup = findTreeNode("Microgrid2")
        val buidlingTreeNode = buidlingGroup as TreeModel<Entity>
        val building1 = BuildingLoad("BUILDING-LOW-${UtilFuncs.counterFormat(5, "5")}", "知味园(餐厅)", "BuildingCanting-${UtilFuncs.unique(16)[0]}", buidlingGroup.id, mutableListOf(), buidlingTreeNode.path())
        val building2 = BuildingLoad("BUILDING-LOW-${UtilFuncs.counterFormat(5, "5")}", "水泵房", "BuildingWaterPump-${UtilFuncs.unique(16)[0]}", buidlingGroup.id, mutableListOf(), buidlingTreeNode.path())
        val building3 = BuildingLoad("BUILDING-LOW-${UtilFuncs.counterFormat(5, "5")}", "问道阁", "BuildingWendao-${UtilFuncs.unique(16)[0]}", buidlingGroup.id, mutableListOf(), buidlingTreeNode.path())
        val building4 = BuildingLoad("BUILDING-LOW-${UtilFuncs.counterFormat(5, "5")}", "绿色楼", "BuildingGreen-${UtilFuncs.unique(16)[0]}", buidlingGroup.id, mutableListOf(), buidlingTreeNode.path())
        val building5 = BuildingLoad("BUILDING-LOW-${UtilFuncs.counterFormat(5, "5")}", "信息中心", "BuildingInfoCenter-${UtilFuncs.unique(16)[0]}", buidlingGroup.id, mutableListOf(), buidlingTreeNode.path())
        val building6 = BuildingLoad("BUILDING-LOW-${UtilFuncs.counterFormat(5, "5")}", "开放楼", "BuildingOpen-${UtilFuncs.unique(16)[0]}", buidlingGroup.id, mutableListOf(), buidlingTreeNode.path())
        buidlingTreeNode.children.add(building1)
        buidlingTreeNode.children.add(building2)
        buidlingTreeNode.children.add(building3)
        buidlingTreeNode.children.add(building4)
        buidlingTreeNode.children.add(building5)
        buidlingTreeNode.children.add(building6)
    }

    fun createBuildingHoude(){
        val buildingEntity = findTreeNode("BuildingHoude")
        val floors = 5
        val rooms = listOf(27, 27, 27, 27, 27)
        val appliances = listOf("热水壶","电视","空调","电脑","手机","用电设备1","用电设备2","用电设备3")
        val buildingTreeNode = buildingEntity as TreeModel<Entity>
        for(i in 0 until floors){
            val floor = FloorLoad("FLOOR-LOW-${UtilFuncs.counterFormat(5, "6")}", "厚德阁${i+1}楼", "WendaoFloor${i+1}-${UtilFuncs.unique(16)[0]}", buildingEntity.id, mutableListOf(), buildingTreeNode.path())
            for (j in 0 until rooms[i]){
                val room_number = (i+1).toString() + String.format("%02d", j+1)
                val room = RoomLoad("ROOM-LOW-${UtilFuncs.counterFormat(5, "7")}", "厚德阁${i+1}楼${room_number}房间", "WendaoFloor${i+1}Room${room_number}-${UtilFuncs.unique(16)[0]}", floor.id, mutableListOf(), floor.path())
                appliances.forEachIndexed{ index, name ->
                    val appliance = Appliance("APPLIANCE-LOW-${UtilFuncs.counterFormat(5, "8")}", "厚德阁${i+1}楼${room_number}房间${name}", "WendaoFloor${i+1}Room${room_number}Appliance${index+1}-${UtilFuncs.unique(16)[0]}", room.id, mutableListOf(), room.path())
                    room.children.add(appliance)
                }
                floor.children.add(room)
            }
            buildingTreeNode.children.add(floor)
        }
    }

    fun createBuildingWendao(){
        val buildingEntity = findTreeNode("BuildingWendao")
        val floors = 3
        val rooms = listOf(18, 17, 17)
        val appliances = listOf("热水壶","电视","空调","电脑","手机","烘干机1","烘干机2","熨斗", "洗衣机1", "洗衣机2")
        val buildingTreeNode = buildingEntity as TreeModel<Entity>
        for(i in 0 until floors){
            val floor = FloorLoad("FLOOR-LOW-${UtilFuncs.counterFormat(5, "6")}", "问道阁${i+1}楼", "WendaoFloor${i+1}-${UtilFuncs.unique(16)[0]}", buildingEntity.id, mutableListOf(), buildingEntity.path())
            for (j in 0 until rooms[i]){
                val room_number = (i+1).toString() + String.format("%02d", j+1)
                val room = RoomLoad("ROOM-LOW-${UtilFuncs.counterFormat(5, "7")}", "问道阁${i+1}楼${room_number}房间", "WendaoFloor${i+1}Room${room_number}-${UtilFuncs.unique(16)[0]}", floor.id, mutableListOf(), floor.path())
                appliances.forEachIndexed{ index, name ->
                    val appliance = Appliance("APPLIANCE-LOW-${UtilFuncs.counterFormat(5, "8")}", "问道阁${i+1}楼${room_number}房间${name}", "WendaoFloor${i+1}Room${room_number}Appliance${index+1}-${UtilFuncs.unique(16)[0]}", room.id, mutableListOf(), room.path())
                    room.children.add(appliance)
                }
                floor.children.add(room)
            }
            buildingTreeNode.children.add(floor)
        }
    }

    fun createBuildingGreen(){
        val buildingEntity = findTreeNode("BuildingGreen")
        val floors = 5
        val rooms = listOf("102", "103", "104", "201", "202", "203", "301", "302", "401", "402", "403", "502", "503", "504")
        val appliances = listOf("立式空调1","立式空调2","专业空调")
        val buildingTreeNode = buildingEntity as TreeModel<Entity>
        for(i in 0 until floors){
            val floor = FloorLoad("FLOOR-LOW-${UtilFuncs.counterFormat(5, "6")}", "绿色楼${i+1}楼", "GreenFloor${i+1}-${UtilFuncs.unique(16)[0]}", buildingEntity.id, mutableListOf(), buildingEntity.path())
            rooms.forEach { room_number ->
                val room_floor = room_number.substring(0, 1).toInt()
                if (room_floor == (i + 1)){
                    val room = RoomLoad("ROOM-LOW-${UtilFuncs.counterFormat(5, "7")}", "绿色楼${i+1}楼${room_number}房间", "GreenFloor${i+1}Room${room_number}-${UtilFuncs.unique(16)[0]}", floor.id, mutableListOf(), floor.path())
                    appliances.forEachIndexed{ index, name ->
                        val appliance = Appliance("APPLIANCE-LOW-${UtilFuncs.counterFormat(5, "8")}", "绿色楼${i+1}楼${room_number}房间${name}", "GreenFloor${i+1}Room${room_number}Appliance${index+1}-${UtilFuncs.unique(16)[0]}", room.id, mutableListOf(), room.path())
                        room.children.add(appliance)
                    }
                    floor.children.add(room)
                }
            }
            buildingTreeNode.children.add(floor)
        }
    }

    fun createBuildingInnovation(){
        val buildingEntity = findTreeNode("BuildingInnovation")
        val floors = 5
        val rooms = listOf("101", "102", "103", "201", "202", "203", "301", "302", "401", "402", "501")
        val appliances = listOf("立式空调1","立式空调2","立式空调3","立式空调4","立式空调5")
        val buildingTreeNode = buildingEntity as TreeModel<Entity>
        for(i in 0 until floors){
            val floor = FloorLoad("FLOOR-LOW-${UtilFuncs.counterFormat(5, "6")}", "创新楼${i+1}楼", "InnovationFloor${i+1}-${UtilFuncs.unique(16)[0]}", buildingEntity.id, mutableListOf(), buildingEntity.path())
            rooms.forEach { room_number ->
                val room_floor = room_number.substring(0, 1).toInt()
                if (room_floor == (i + 1)){
                    val room = RoomLoad("ROOM-LOW-${UtilFuncs.counterFormat(5, "7")}", "创新楼${i+1}楼${room_number}房间", "InnovationFloor${i+1}Room${room_number}-${UtilFuncs.unique(16)[0]}", floor.id, mutableListOf(), floor.path())
                    appliances.forEachIndexed{ index, name ->
                        val appliance = Appliance("APPLIANCE-LOW-${UtilFuncs.counterFormat(5, "8")}", "创新楼${i+1}楼${room_number}房间${name}", "InnovationFloor${i+1}Room${room_number}Appliance${index+1}-${UtilFuncs.unique(16)[0]}", room.id, mutableListOf(), room.path())
                        room.children.add(appliance)
                    }
                    floor.children.add(room)
                }
            }
            buildingTreeNode.children.add(floor)
        }
    }

    fun createBuildingOpen(){
        val buildingEntity = findTreeNode("BuildingOpen")
        val floors = 5
        val rooms = listOf("101", "201", "301", "302", "303", "304", "305", "401", "402", "403", "404", "405", "501", "502", "503")
        val appliances = listOf("立式空调1","立式空调2")
        val buildingTreeNode = buildingEntity as TreeModel<Entity>
        for(i in 0 until floors){
            val floor = FloorLoad("FLOOR-LOW-${UtilFuncs.counterFormat(5, "6")}", "开放楼${i+1}楼", "OpenFloor${i+1}-${UtilFuncs.unique(16)[0]}", buildingEntity.id, mutableListOf(), buildingEntity.path())
            rooms.forEach { room_number ->
                val room_floor = room_number.substring(0, 1).toInt()
                if (room_floor == (i + 1)){
                    val room = RoomLoad("ROOM-LOW-${UtilFuncs.counterFormat(5, "7")}", "开放楼${i+1}楼${room_number}房间", "OpenFloor${i+1}Room${room_number}-${UtilFuncs.unique(16)[0]}", floor.id, mutableListOf(), floor.path())
                    appliances.forEachIndexed{ index, name ->
                        val appliance = Appliance("APPLIANCE-LOW-${UtilFuncs.counterFormat(5, "8")}", "开放楼${i+1}楼${room_number}房间${name}", "OpenFloor${i+1}Room${room_number}Appliance${index+1}-${UtilFuncs.unique(16)[0]}", room.id, mutableListOf(), room.path())
                        room.children.add(appliance)
                    }
                    floor.children.add(room)
                }
            }
            buildingTreeNode.children.add(floor)
        }
    }

    fun createBuildingZhiwei(){
        val buildingEntity = findTreeNode("BuildingCanting")
        val floors = 2
        val rooms = listOf("101", "102", "201", "202", "203", "204", "205")
        val appliances = listOf("立式空调1","立式空调2","立式空调3")
        val buildingTreeNode = buildingEntity as TreeModel<Entity>
        for(i in 0 until floors){
            val floor = FloorLoad("FLOOR-LOW-${UtilFuncs.counterFormat(5, "6")}", "知味园${i+1}楼", "CantingFloor${i+1}-${UtilFuncs.unique(16)[0]}", buildingEntity.id, mutableListOf(), buildingEntity.path())
            rooms.forEach { room_number ->
                val room_floor = room_number.substring(0, 1).toInt()
                if (room_floor == (i + 1)){
                    val room = RoomLoad("ROOM-LOW-${UtilFuncs.counterFormat(5, "7")}", "知味园${i+1}楼${room_number}房间", "CantingFloor${i+1}Room${room_number}-${UtilFuncs.unique(16)[0]}", floor.id, mutableListOf(), floor.path())
                    appliances.forEachIndexed{ index, name ->
                        val appliance = Appliance("APPLIANCE-LOW-${UtilFuncs.counterFormat(5, "8")}", "知味园${i+1}楼${room_number}房间${name}", "CantingFloor${i+1}Room${room_number}Appliance${index+1}-${UtilFuncs.unique(16)[0]}", room.id, mutableListOf(), room.path())
                        room.children.add(appliance)
                    }
                    floor.children.add(room)
                }
            }
            buildingTreeNode.children.add(floor)
        }
    }

    fun createBuildingCanting(){
        val buildingEntity = findTreeNode("ZhiweiImportant")
        val buildingTreeNode = buildingEntity as TreeModel<Entity>
        val floor = FloorLoad("FLOOR-LOW-${UtilFuncs.counterFormat(5, "2")}", "知味园(餐厅)_1楼", "Zhiwei_Canting_Floor1-${UtilFuncs.unique(16)[0]}", buildingEntity.id, mutableListOf(), buildingEntity.path())
        val room = RoomLoad("ROOM-LOW-${UtilFuncs.counterFormat(5, "3")}", "知味园(餐厅)_1楼_101房间", "Zhiwei_Canting_Floor1_Room101-${UtilFuncs.unique(16)[0]}", floor.id, mutableListOf(), floor.path())
        val appliance = Appliance("APPLIANCE-LOW-${UtilFuncs.counterFormat(5, "4")}", "知味园(餐厅)_1楼_101房间_重要负荷", "CantingFloor1_Room101_ApplianceImportant-${UtilFuncs.unique(16)[0]}", room.id, mutableListOf(), room.path())
        room.children.add(appliance)
        floor.children.add(room)
        buildingTreeNode.children.add(floor)
    }
}

sealed class MetaSystem (
    var id: String,
    var name: String,
    var ip: String,
    var port: Int,
    var lifespan: Long
)

class CloudComputing (id: String, name: String, ip: String, port: Int, lifespan: Long) :
    MetaSystem(id, name, ip, port, lifespan)

class MessageBroker(id: String, name: String, ip: String, port: Int, lifespan: Long,
    clientId: String, username:String, password:String, keepAlive: Int = 12000, useSSL:Boolean = false, reConnect:Boolean = true) :
    MetaSystem(id, name, ip, port, lifespan)

class EdgeComputing (id: String, name: String, ip: String, port: Int, lifespan: Long) :
    MetaSystem(id, name, ip, port, lifespan), DeepCopy<MetaSystem> {
    override fun deepCopy(): MetaSystem {
        return EdgeComputing(id, name, ip, port, lifespan)
    }
}

class SmartMeter (id: String, name: String, ip: String, port: Int, lifespan: Long) :
    MetaSystem(id, name, ip, port, lifespan)

class SmartSocket(id: String, name: String, ip: String, port: Int, lifespan: Long) :
    MetaSystem(id, name, ip, port, lifespan)


data class InfoSets (
    val cloudIns: MetaSystem,
    val brokerIns: MetaSystem,
    val edgeIns: MutableList<MetaSystem>,
    val meterIns: MutableList<MetaSystem>,
    val socketIns: MutableList<MetaSystem>
)


class InfoMaster {

    lateinit var cloud: MetaSystem
    lateinit var broker: MetaSystem
    var edges: MutableList<MetaSystem> = mutableListOf()
    var meters: MutableList<MetaSystem> = mutableListOf()
    var sockets: MutableList<MetaSystem> = mutableListOf()

    init {
        UtilFuncs.counterFormat(length = 5, refresh = true)
        createCloudComputing()
        createBroker()
//        createMeters()
//        createSocket()
    }

    fun createIots(root: TreeModel<Entity>){
        createEdgeComputing(root)
        createMeters(root)
        createSocket(root)
    }

    fun saveMetaFile(savePath: String){
        val target = InfoSets(cloud, broker, edges, meters, sockets)
        try {
            PrintWriter(FileWriter(savePath)).use {
                val rootStr = Gson().toJson(target)
                it.write(rootStr)
            }
        }catch (e: Exception){
            e.printStackTrace()
        }
    }

    private fun createCloudComputing(){
        cloud = CloudComputing("CLOUD-HUADONG-${UtilFuncs.counterFormat(5, "0")}", "云计算中心", "beepower.com.cn", 8080, 1767196800000)
    }

    private fun createBroker(){
        broker = MessageBroker("MOSQUITTO-HUADONG-${UtilFuncs.counterFormat(5, "0")}", "中间件", "beepower.com.cn", 9883, 1767196800000,
            "9001030", "scn", "123456")
    }

    fun createEdgeComputing(root: TreeModel<Entity>){
        val beginStr = "8657000"
        val recursionList = mutableListOf(root)
        while (recursionList.size > 0){
            val curNode = recursionList[0]
            if (curNode is FloorLoad){
                val edge = EdgeComputing(UtilFuncs.counterFormat(5, beginStr), curNode.name+"网关", "", 9883, 1767196800000)
                edges.add(edge)
            }
            recursionList.removeAt(0)
            curNode.children.forEach { recursionList.add(it as TreeModel<Entity>) }
        }

        val extra1 = EdgeComputing(UtilFuncs.counterFormat(5, beginStr), "进线开关(计量点)网关", "", 9883, 1767196800000)
        val extra2 = EdgeComputing(UtilFuncs.counterFormat(5, beginStr), "微网1网关", "", 9883, 1767196800000)
        val extra3 = EdgeComputing(UtilFuncs.counterFormat(5, beginStr), "微网2网关", "", 9883, 1767196800000)
        edges.add(extra1)
        edges.add(extra2)
        edges.add(extra3)
//        edges.forEach { println("${it.id}-${it.name}") }
    }

    private fun createMeters(root: TreeModel<Entity>){
        val recursionList = mutableListOf(root)
        while (recursionList.size > 0){
            val curNode = recursionList[0]
            val nodeEntity = curNode as Entity
            if (curNode is InlineSwitch){
                val meter = SmartMeter("Trm-virtual3-${UtilFuncs.counterFormat(5, "0")}", "${nodeEntity.name}电表(3相)", "", 0, 1767196800000)
                meters.add(meter)
            }
            if ((curNode is OutlineSwitch) || (curNode is ChargingPile) || (curNode is Diesel) || (curNode is Photovoltaic) ||
                (curNode is BatteryStation) || (curNode is BuildingLoad) || (curNode is FloorLoad) || (curNode is RoomLoad || curNode is ContactSwitch)){
                val meter = SmartMeter("Trm-virtual-${UtilFuncs.counterFormat(5, "0")}", "${nodeEntity.name}电表", "", 0, 1767196800000)
                meters.add(meter)
            }
            recursionList.removeAt(0)
            curNode.children.forEach { recursionList.add(it as TreeModel<Entity>) }
        }
//        meters.forEach { println("${it.id}-${it.name}") }
    }

    private fun createSocket(root: TreeModel<Entity>){
        val recursionList = mutableListOf(root)
        while (recursionList.size > 0){
            val curNode = recursionList[0]
            val nodeEntity = curNode as Entity
            if (curNode is Appliance){
                val socket = SmartSocket("Sck-20-${UtilFuncs.counterFormat(5, "0")}", "${nodeEntity.name}插座", "", 0, 1767196800000)
                sockets.add(socket)
            }
            recursionList.removeAt(0)
            curNode.children.forEach { recursionList.add(it as TreeModel<Entity>) }
        }
//        sockets.forEach { println("${it.id}-${it.name}") }
    }
}


data class IotLower (
    val edgeIns: MetaSystem,
    val meters: List<MetaSystem>,
    val sockets: List<MetaSystem>
)

data class IotUpper (
    val cloudIns: MetaSystem,
    val brokerIns: MetaSystem,
    val children: MutableList<IotLower>
)

class LogicMaster(p: PhysicalMaster, i: InfoMaster) {
    val physicalIns: PhysicalMaster = p
    val infoRootIns: InfoMaster = i
    var result: IotUpper?=null

    init {
        buildingLogic()
    }

    fun saveMetaFile(savePath: String){
        try {
            PrintWriter(FileWriter(savePath)).use {
                val rootStr = Gson().toJson(result)
                it.write(rootStr)
            }
        }catch (e: Exception){
            e.printStackTrace()
        }
    }

    fun filterMeters(todoList: List<String>): List<MetaSystem>{
        val meters = infoRootIns.meters
        val findMeters = mutableListOf<MetaSystem>()
        meters.forEach { mit ->
            val ret = todoList.find { mit.name.contains(it + "电表")}
            if (ret != null) findMeters.add(mit)
        }
        return findMeters
    }


    fun buildingLogic(){
        val edges = infoRootIns.edges
        val meters = infoRootIns.meters
        val sockets = infoRootIns.sockets


        val inSwitchList = listOf("进线开关(计量点)","备用1", "备用2", "水泵房(可中断)", "污水站", "备用3", "知味园(餐厅)", "创新楼(总出线)", "路灯", "区域2联络开关")
        val microList1 = listOf("柴油发电机1","创新楼光伏","厚德阁光伏","电池储能1","微网1分路开关","创新楼","厚德阁", "区域1联络开关")
        val microList2 = listOf("柴油发电机2", "绿色楼光伏", "知味园光伏", "电池储能2", "微网2分路开关", "知味园(餐厅)", "水泵房", "问道阁", "绿色楼", "信息中心", "开放楼")

        result = IotUpper(infoRootIns.cloud, infoRootIns.broker, mutableListOf())

        edges.forEach { edge ->
            when (edge.id){
                "86570000029" -> {
                    val meters = filterMeters(inSwitchList)
                    val lower = IotLower(edge, meters, mutableListOf())
                    result!!.children.add(lower)
                }
                "86570000030" -> {
                    val meters = filterMeters(microList1)
                    val lower = IotLower(edge, meters, mutableListOf())
                    result!!.children.add(lower)
                }
                "86570000031" -> {
                    val meters = filterMeters(microList2)
                    val lower = IotLower(edge, meters, mutableListOf())
                    result!!.children.add(lower)
                }
                else -> {
                    val matchName = edge.name.replace("网关","")
                    val findMeters = meters.filter { it.name.contains(matchName) }
                    val findSockets = sockets.filter { it.name.contains(matchName) }
                    val lower = IotLower(edge, findMeters, findSockets)
                    result!!.children.add(lower)
                }
            }
        }
    }
}


fun main(args: Array<String>) {
//    PhysicalMaster().depthTraversal()
//    PhysicalMaster().widthTraversal()
//    val p = PhysicalMaster()
//    PhysicalMaster().saveMetaFile("src/main/resources/physical.json")
//    val i = InfoMaster()
//    i.createIots(p.root as TreeModel<Entity>)
//    i.saveMetaFile("src/main/resources/infosystem.json")
//    LogicMaster(p, i).saveMetaFile("src/main/resources/logic.json")
    val station = UtilFuncs.readFile("src/main/resources/physical.json")
    val entity = Gson().fromJson(station, PhysicalMaster::class.java)
    println(entity)
}